import {
  type Scene,
  Mesh,
  PlaneGeometry,
  MeshBasicMaterial,
  Color,
  SRGBColorSpace,
  CanvasTexture,
} from 'three'
import type { Options } from '@/try-on/config'
export class VideoBg {
  scene: Scene
  width: number
  height: number
  needUpdate: boolean = false
  plane?: Mesh
  video?: HTMLVideoElement
  canvas: HTMLCanvasElement
  ctx: CanvasRenderingContext2D
  options: Options
  constructor(
    scene: Scene,
    width: number,
    height: number,
    video: HTMLVideoElement,
    options: Options,
  ) {
    this.options = options
    this.scene = scene
    this.width = width
    this.height = height
    this.video = video
    this.canvas = document.createElement('canvas')
    this.ctx = this.canvas.getContext('2d')!
    // document.body.appendChild(this.canvas)
    this.updateBackgroud()
    // const result = document.querySelector('#result')
    // result?.appendChild(this.canvas)
  }
  updateDimensions(width: number, height: number) {
    this.width = width
    this.height = height
    this.needUpdate = true
  }
  createGeometry() {
    return new PlaneGeometry(this.width, this.height)
  }
  createMaterial() {
    if (!this.video) {
      return new MeshBasicMaterial({ color: new Color(0xff0000) })
    }
    const videoTexture = new CanvasTexture(this.canvas)
    videoTexture.colorSpace = SRGBColorSpace
    // if (this.video.videoWidth > this.video.videoHeight) {
    //   this.cropToAspect(videoTexture, this.video)
    // }
    const material = new MeshBasicMaterial({
      map: videoTexture,
    })
    material.depthWrite = false
    return material
  }
  createNewPlane() {
    const geometry = this.createGeometry()
    const material = this.createMaterial()
    this.plane = new Mesh(geometry, material)
    this.plane.name = 'background'
    this.plane.renderOrder = 0
    this.addPlaneToScene()
  }
  addPlaneToScene() {
    if (this.plane) {
      this.scene.add(this.plane)
      this.plane.position.set(0, 0, 0)
    }
  }
  // 3) 视频居中裁成 3:4（宽:高=3:4）
  // cropToAspect(texture: VideoTexture, vid: HTMLVideoElement, targetW = 3, targetH = 4) {
  //   const vw = vid.videoWidth,
  //     vh = vid.videoHeight
  //   const srcAspect = vw / vh
  //   const dstAspect = targetW / targetH

  //   // 计算 offset/repeat（UV 空间里）
  //   let repeatX = 1,
  //     repeatY = 1,
  //     offsetX = 0,
  //     offsetY = 0

  //   if (srcAspect > dstAspect) {
  //     // 视频比目标更“宽” -> 裁宽度
  //     const newW = dstAspect * vh
  //     repeatX = newW / vw
  //     offsetX = (1 - repeatX) / 2 // 居中
  //   } else {
  //     // 视频比目标更“高” -> 裁高度
  //     const newH = vw / dstAspect
  //     repeatY = newH / vh
  //     offsetY = (1 - repeatY) / 2 // 居中
  //   }
  //   texture.repeat.set(repeatX, repeatY)
  //   texture.offset.set(offsetX, offsetY)
  // }
  removePlaneFromSence() {
    // this.scene.remove(this.plane!)
    this.plane!.geometry = this.createGeometry()
    this.plane!.material = this.createMaterial()
  }
  updateBackgroud() {
    if (this.video?.videoWidth) {
      this.drawVideoToCanvas(this.video)
    }
    requestAnimationFrame(this.updateBackgroud.bind(this))
  }
  update() {
    if (!this.plane) {
      this.createNewPlane()
    }
    if (this.needUpdate) {
      this.removePlaneFromSence()
      // this.createNewPlane()
      this.needUpdate = false
    }
    this.plane!.material = this.createMaterial()
  }
  drawVideoToCanvas(video: HTMLVideoElement) {
    const { detectWidth } = this.options.tryOn
    let aspect = 1
    if (this.options.tryOn.sceneAspect == 'full') {
      aspect = window.innerWidth / window.innerHeight
    } else {
      aspect = this.options.tryOn.sceneAspect as number
    }
    this.canvas.width = detectWidth
    this.canvas.height = detectWidth / aspect
    const targetAspect = aspect
    const videoAspect = video.videoWidth / video.videoHeight
    let sx = 0,
      sy = 0,
      sw = video.videoWidth,
      sh = video.videoHeight

    if (videoAspect > targetAspect) {
      // 视频太宽 → 裁剪宽度
      sh = video.videoHeight
      sw = sh * targetAspect
      sx = (video.videoWidth - sw) / 2
      sy = 0
    } else if (videoAspect < targetAspect) {
      // 视频太高 → 裁剪高度
      sw = video.videoWidth
      sh = sw / targetAspect
      sx = 0
      sy = (video.videoHeight - sh) / 2
    }
    this.ctx.translate(this.canvas.width, 0)
    this.ctx.scale(-1, 1)
    if (videoAspect != targetAspect) {
      this.ctx?.drawImage(video, sx, sy, sw, sh, 0, 0, this.canvas.width, this.canvas.height)
    } else {
      this.ctx.drawImage(video, 0, 0, this.canvas.width, this.canvas.height)
    }
  }
}
